package sunbt.gistools.util;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;

/**
 * @author sunbt
 * @version 1.0
 * @date 2025/7/17 22:34
 * GeoJson工具类
 */
public class GeoJsonUtils {

    /**
     * 将经纬度数组转换为 MultiPoint GeoJSON 对象
     *
     * @param coordinatesArray 经纬度数组，每个元素是一个包含经度和纬度的数组
     * @return GeoJSON 字符串
     */
    public static String convertToMultiPointGeoJson(double[][] coordinatesArray) {
        JSONObject geometry = new JSONObject();
        geometry.put("type", "MultiPoint");
        JSONArray coordinates = new JSONArray();
        for (double[] coord : coordinatesArray) {
            JSONArray point = new JSONArray();
            point.add(coord[0]);
            point.add(coord[1]);
            coordinates.add(point);
        }
        geometry.put("coordinates", coordinates);
        return geometry.toJSONString();
    }

    /**
     * 将经纬度数组转换为 Point GeoJSON 对象
     *
     * @param coordinate 经纬度数组，包含一个经度和纬度的数组
     * @return GeoJSON 字符串
     */
    public static String convertToPointGeoJson(double[] coordinate) {
        JSONObject geometry = new JSONObject();
        geometry.put("type", "Point");
        JSONArray coordinates = new JSONArray();
        coordinates.add(coordinate[0]); // 经度
        coordinates.add(coordinate[1]); // 纬度
        geometry.put("coordinates", coordinates);
        return geometry.toJSONString();
    }

    /**
     * 将给定的经纬度字符串转换为GeoJSON格式的Point几何对象
     * 此方法首先将字符串形式的经纬度转换为double类型，然后调用另一个方法完成实际的转换
     *
     * @param longitude 经度字符串
     * @param latitude  纬度字符串
     * @return 表示Point几何对象的GeoJSON字符串
     */
    public static String convertToPointGeoJson(String longitude, String latitude) {
        // 将经纬度字符串转换为double类型数组，为转换为GeoJSON格式做准备
        double[] coordinatesArray = {
                Double.parseDouble(longitude), Double.parseDouble(latitude)
        };
        // 调用另一个方法，将转换后的经纬度数组传递给它，以获取GeoJSON格式的Point几何对象
        return convertToPointGeoJson(coordinatesArray);
    }

    /**
     * 将给定的经纬度转换为GeoJSON MultiPoint格式
     * 此方法接收单个经纬度坐标，并将其封装成一个包含单个点的MultiPoint结构
     *
     * @param longitude 经度值，以字符串形式表示
     * @param latitude  纬度值，以字符串形式表示
     * @return 返回表示MultiPoint的GeoJSON字符串
     */
    public static String convertToMultiPointGeoJson(String longitude, String latitude) {
        // 创建一个二维数组来存储经纬度坐标，以满足GeoJSON MultiPoint格式的要求
        double[][] coordinatesArray = {
                {Double.parseDouble(longitude), Double.parseDouble(latitude)}
        };
        // 调用重载方法，将坐标数组转换为GeoJSON MultiPoint字符串
        return convertToMultiPointGeoJson(coordinatesArray);
    }

    /**
     * 将点数组转换为 LineString GeoJSON 对象
     *
     * @param pointsArray 点数组，每个点是一个包含经度和纬度的数组
     * @return GeoJSON 字符串
     */
    public static String convertToLineStringGeoJson(double[][] pointsArray) {
        if (pointsArray.length < 2) {
            return null;
        }
        // 创建 LineString 对象
        JSONObject geometry = new JSONObject();
        geometry.put("type", "LineString");
        // 创建坐标数组
        JSONArray coordinates = new JSONArray();
        for (double[] point : pointsArray) {
            JSONArray coordinate = new JSONArray();
            coordinate.add(point[0]); // 经度
            coordinate.add(point[1]); // 纬度
            coordinates.add(coordinate);
        }
        // 将坐标数组添加到 Geometry 中
        geometry.put("coordinates", coordinates);
        // 返回 GeoJSON 字符串
        return geometry.toJSONString();
    }

    /**
     * 将点数组转换为 MultiLineString GeoJSON 对象
     *
     * @param linesArray 二维数组，每个内部数组表示一个线段，线段由多个点组成
     * @return GeoJSON 字符串
     */
    public static String convertToMultiLineStringGeoJson(double[][][] linesArray) {
        // 创建 MultiLineString 对象
        JSONObject geometry = new JSONObject();
        geometry.put("type", "MultiLineString");
        // 创建坐标数组
        JSONArray multiLineCoordinates = new JSONArray();
        for (double[][] line : linesArray) {
            if (line.length < 2) {
                return null;
            }
            JSONArray lineCoordinates = new JSONArray();
            for (double[] point : line) {
                JSONArray coordinate = new JSONArray();
                coordinate.add(point[0]); // 经度
                coordinate.add(point[1]); // 纬度
                lineCoordinates.add(coordinate);
            }
            multiLineCoordinates.add(lineCoordinates);
        }
        // 将坐标数组添加到 Geometry 中
        geometry.put("coordinates", multiLineCoordinates);
        // 返回 GeoJSON 字符串
        return geometry.toJSONString();
    }

    public static void main(String[] args) {
        // 将经纬度数组转换为 MultiPoint GeoJSON 对象
        double[][] coordinatesArray = {
                {-122.4194, 37.7749}
        };
        String geoJsonString = convertToMultiPointGeoJson(coordinatesArray);
        System.out.println(geoJsonString);

        // 将点数组转换为 LineString GeoJSON 对象
        double[][] pointsArray = {
                {-122.4194, 37.7749},
                {-123.4194, 38.7749},
                {-121.4194, 36.7749}
        };
        geoJsonString = convertToLineStringGeoJson(pointsArray);
        System.out.println(geoJsonString);

        // 将点数组转换为 MultiLineString GeoJSON 对象
        double[][][] linesArray = {
                {
                        {-122.4194, 37.7749},
                        {-123.4194, 38.7749}
                },
                {
                        {-121.4194, 36.7749},
                        {-120.4194, 35.7749}
                }
        };

        geoJsonString = convertToMultiLineStringGeoJson(linesArray);
        System.out.println(geoJsonString);
    }

}
